﻿/*
 
    This file is part of AnkhBG.

    AnkhBG is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    AnkhBG is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with AnkhBG.  If not, see <http://www.gnu.org/licenses/>.
 
 */


using Glider.Common.Objects;
using System.Windows.Forms;
using System.Collections.Generic;
using System;

namespace AnkhBG
{

    public class QueueManager
    {
        #region Public Fields
        public Settings settings = Settings.Instance;


        // Check if we are queued by looking for the MiniMap-Icon
        public static bool IsQueued
        {
            get
            {
                GInterfaceObject frame = GContext.Main.Interface.GetByName("MiniMapBattlefieldFrame");
                return (frame != null && frame.IsVisible);
            }
        }

        // Check if we can enter a battleground by looking for the StaticPopup-frames
        public static bool CanEnter
        {
            get
            {
                for (int i = 1; i <= 4; ++i)
                {
                    GInterfaceObject obj = GContext.Main.Interface.GetByName("StaticPopup" + i.ToString());
                    if (obj == null || !obj.IsVisible)
                        continue;

                    GInterfaceObject text = obj.GetChildObject("StaticPopup" + i.ToString() + "Text");
                    if (text == null || !text.LabelText.StartsWith("You are now eligible to enter"))
                        continue;

                    return true;
                }

                return false;
            }
        }

        // Check if the battleground is over by looking for the Leave-Button
        public static bool CanLeave
        {
            get
            {
                GInterfaceObject obj = GContext.Main.Interface.GetByName("WorldStateScoreFrameLeaveButton");
                if (obj != null && obj.IsVisible)
                    return true;
                else
                    return false;
            }
        }
        #endregion


        #region Contructors

        public QueueManager()
        {
        }

        ~QueueManager()
        {
        }

        #endregion

        #region Public Methods
        // Accept the Queue-Dialog / Enter the battleground
        // returns an error-code (anything > 0 means an error occured)
        public int Enter()
        {
            if (CanEnter)
            {
                int popup = 0;
                for (int i = 1; i <= 4; ++i)
                {
                    GInterfaceObject obj = GContext.Main.Interface.GetByName("StaticPopup" + i.ToString());
                    if (obj == null || !obj.IsVisible)
                        continue;
                    GInterfaceObject text = obj.GetChildObject("StaticPopup" + i.ToString() + "Text");
                    if (text == null || !text.LabelText.StartsWith("You are now eligible to enter"))
                        continue;
                    popup = i;
                    break;
                }
                if (popup > 0)
                {
                    GInterfaceObject obj = GContext.Main.Interface.GetByName("StaticPopup" + popup.ToString() + "Button1");
                    if (obj != null && obj.IsVisible)
                    {
                        GContext.Main.EnableCursorHook();
                        obj.Hover();
                        obj.ClickMouse(false);
                        GContext.Main.DisableCursorHook();

                        return 0;
                    }
                    else
                        return 3;
                }
                else
                    return 2;
            }
            else
                return 1; // can't enter yet
        }

        // Leave the Queue
        // returns an error-code (anything > 0 means an error occured)
        public int Leave()
        {
            if (CanLeave)
            {
                GInterfaceObject obj = GContext.Main.Interface.GetByName("WorldStateScoreFrameLeaveButton");
                GContext.Main.EnableCursorHook();
                obj.Hover();
                obj.ClickMouse(false);
                GContext.Main.DisableCursorHook();
                return 0;
            }
            else
                return 1;
        }

        // Queue up
        // returns an error-code (anything > 0 means an error occured)
        public int Queue()
        {
            if (IsQueued)
            {
                return 1; // is already queued
            }

            GUnit[] units = GObjectList.GetUnits();
            GUnit npc = null;
            NPCManager Battlemasters = new NPCManager();

            //closest, specific, random

            if (settings.QueueType.Equals("specific"))
                npc = Battlemasters.getBattlemaster(settings.QueueBG);
            else
                npc = Battlemasters.getBattlemaster(settings.QueueType);

            if (npc != null)
            {
                GContext.Main.ClearTarget();

                if (npc != null && !npc.IsValid)
                    npc = GObjectList.FindUnit(npc.GUID);

                double approach_distance = 1.5f;
                Main.Instance.Window.Log("Trying to approach " + npc.Name);
                if (!npc.Approach(approach_distance))
                    GContext.Main.Debug("Couldn't approach " + npc.Name);

                Main.Instance.Window.Log("Trying to talk to " + npc.Name + ".");

                for (int tries = 3; tries >= 0; --tries)
                {
                    bool interacted = false;
                    if (npc != null && npc.IsValid)
                    {
                        GContext.Main.EnableCursorHook();
                        npc.Face();
                        interacted = npc.Interact();
                        GContext.Main.DisableCursorHook();
                    }
                    else if (!npc.IsValid)
                        GContext.Main.Debug("AnkhBG: Unit was not valid, can't interact.");

                    if (interacted == false)
                    {
                        GContext.Main.Debug("AnkhBG: Interaction failed, retrying in 2 minutes");
                        Main.Instance.Window.LogError("Interaction failed, retrying in 2 minutes");
                        //Starts timer to retry queueing in 120seconds
                        //Main.Instance.Window.RetryInteractCd.Start();
                        for (int delay = 120; delay > 0; delay--)
                        {
                            if (Main.Instance.running)
                            {
                                System.Threading.Thread.Sleep(1000);
                                Main.Instance.Window.StatusText.Text = "Retrying interaction in: " + (delay - 1) + " seconds";
                            }
                            else
                            {
                                Main.Instance.Window.StatusText.Text = "Stopped";
                                tries = -1;
                            }
                        }
                        if (Main.Instance.running)
                        {
                            Main.Instance.Window.StatusText.Text = "Running";
                            GContext.Main.Debug("AnkhBG: Retrying interaction");
                            Main.Instance.Window.Log("Retrying interaction");
                            return 0;
                        }
                        else
                            tries = -1;
                    }
                    else
                    {
                        // Try multiple times to interact if window wasn't found
                        System.Threading.Thread.Sleep(1000);

                        GInterfaceObject BattlefieldJoinFrame = GContext.Main.Interface.GetByName("BattlefieldFrameJoinButton");
                        if (BattlefieldJoinFrame != null && BattlefieldJoinFrame.IsVisible)
                        { // Join Battle
                            GContext.Main.EnableCursorHook();
                            BattlefieldJoinFrame.Hover();
                            BattlefieldJoinFrame.ClickMouse(false);
                            Main.Instance.Window.Log("We should be queued now.");
                            GContext.Main.DisableCursorHook();
                            GContext.Main.ClearTarget();
                            break;
                        }
                        else
                        { // Join-Button was not found
                            if (tries == 0)
                            {
                                Main.Instance.Window.LogError("Couldn't find Battleground-Window.");
                                return 4; // Join-Button was not found
                            }
                            else
                            {
                                System.Threading.Thread.Sleep(1000);
                                continue; // we still have more tries
                            }
                        }
                    }
                }
                return 0; // no error
            }
            else
            {
                return 1;
            }

        #endregion
        }


    }
}